﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWS.SiteManager.Core.Model;
using System.IO;

namespace IWS.SiteManager.Core.Model
{
	public class ContentRepository
	{
		SiteManager _DB;

		public ContentRepository()
		{
			_DB = DBFactory.GetProvider();
		}

		/// <summary>
		/// gets a page by its id
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public Content GetContent(int id)
		{
			var page = _DB.Contents.SingleOrDefault(o => o.ID == id);

			if (page == null) //why did I do this? 
				return null;

			return page;
		}
		/// <summary>
		/// Load a page by its permalink. 
		/// </summary>
		/// <param name="permalink"></param>
		/// <returns></returns>
		public Content GetPage(string section, string permalink)
		{
			return _DB.Contents.SingleOrDefault(o => o.SectionID == section && o.Permalink == permalink.Trim().ToLower());
		}
		/// <summary>
		/// gets the configured default page.
		/// </summary>
		/// <returns></returns>
		public Content GetIndexPage(string section)
		{
			var data = _DB.Sections.SingleOrDefault(o => o.ID == section);

			Content page = null;

			if (data != null && data.DefaultContentID.HasValue)
				page = _DB.Contents.SingleOrDefault(o => o.ID == data.DefaultContentID.Value);

			return page;
		}
		public string GetSectionIDForPage(int id)
		{
			var section = _DB.Contents.Where(o => o.ID == id).Select(o => o.SectionID).SingleOrDefault();
			return section;
		}
		public void SaveContent(Content content)
		{
			Section section = null;

			if (_DB.Sections.Where(o => o.ID == content.SectionID).Count() == 0)
			{
				section = new Section();
				section.ID = content.SectionID;
				section.Description = "Auto-generated section for new page.";
				_DB.Sections.InsertOnSubmit(section);
				_DB.SubmitChanges();
			}

			//take current version, push it to content history, overwrite current with new. 
			Content old = this.GetContent(content.ID);
			if (old != null)
			{
				//archive old version. 
				ContentHistory row = new ContentHistory();
				row.ContentID = content.ID;
				row.Body = old.Body;
				row.CreatedUtc = DateTime.UtcNow;
				_DB.ContentHistories.InsertOnSubmit(row);
				_DB.SubmitChanges();


				old.LoadFromExisting(content); //load current values
			}
			else
			{
				old = content;
				_DB.Contents.InsertOnSubmit(old);
			}


			_DB.SubmitChanges();

			if (section != null) //was a new one. set the default content id.
			{
				section.DefaultContentID = content.ID;
				_DB.SubmitChanges();
			}
		}
		public void DeleteContent(int id)
		{
			var data = _DB.Contents.SingleOrDefault(o => o.ID == id);
			if (data != null)
			{
				//remove conflicts first. 
				var section = this.GetSectionByID(data.SectionID);
				if (section != null)
				{
					section.DefaultContentID = null;
					_DB.SubmitChanges();
				}

				_DB.Contents.DeleteOnSubmit(data);
				_DB.SubmitChanges();
			}
		}
		public IQueryable<Content> GetQueriableContent()
		{
			return _DB.Contents;
		}

		/// <summary>
		/// gets the configured default section
		/// </summary>
		/// <returns></returns>
		public string GetDefaultSection()
		{
			return SettingCache.Current.GetSetting(Constants.DefaultSection).Value;
		}
		/// <summary>
		/// returns a list of page contents for a specific section. Excludes content body, head and meta details. 
		/// </summary>
		/// <param name="section"></param>
		/// <returns></returns>
		public List<Content> GetSectionPages(string section)
		{
			return _DB.Contents.Where(o=> o.SectionID == section && o.ContentTypeID == (int)Core.ContentType.Page).ToList();
		}
		public void SaveSection(Section section)
		{
			var data = this.GetSectionByID(section.ID);

			if (data == null)
			{
				data = section;
				_DB.Sections.InsertOnSubmit(data);
			}
			else
				data.LoadFromExisting(section);

			_DB.SubmitChanges();
		}
		public void DeleteSection(string id)
		{
			Section s = _DB.Sections.SingleOrDefault(o => o.ID == id);
			if (s != null)
			{
				s.DefaultContentID = null; //remove any FK problems. 
				_DB.SubmitChanges();

				_DB.Sections.DeleteOnSubmit(s);
				_DB.SubmitChanges();
			}
		}
		public IQueryable<Section> GetQueryableSections()
		{
			return _DB.Sections;
		}

		/// <summary>
		/// Get a section by its id
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public Section GetSectionByID(string id)
		{
			return _DB.Sections.SingleOrDefault(o => o.ID == id);;
		}
		/// <summary>
		/// Gets all sections
		/// </summary>
		/// <returns></returns>
		public List<Section> GetAllSections(bool deepload)
		{
			var list = _DB.Sections.ToList();
			if (deepload)
			{
				foreach (var item in list)
				{
					item.Pages = GetSectionPages(item.ID);
				}
			}
			return list;
		}

		/// <summary>
		/// Gets a page history by id. 
		/// </summary>
		/// <param name="pageID"></param>
		/// <returns></returns>
		public IQueryable<ContentHistory> GetQueryableContentHistory(int contentID)
		{
			return _DB.ContentHistories.Where(o => o.ContentID == contentID);
		}
		public void SaveContentHistory(ContentHistory history)
		{
			var data = _DB.ContentHistories.SingleOrDefault(o => o.ID == history.ID);
			if (data == null)
			{
				data = history;
				_DB.ContentHistories.InsertOnSubmit(data);
			}
			else
				data.LoadFromExisting(history);

			_DB.SubmitChanges();
		}

		public void WriteSitemap(string rootFolder)
		{
			var filename_setting = SettingCache.Current.GetSetting(Constants.SitemapOutputFile);

			var host_setting = SettingCache.Current.GetSetting(Constants.SiteHostname);

			string filename = "sitemap.xml";
			if (filename_setting != null)
				filename = filename_setting.Value;

			SiteMap.urlset sitemap = new IWS.SiteManager.Core.SiteMap.urlset();
			List<SiteMap.tUrl> urls = new List<IWS.SiteManager.Core.SiteMap.tUrl>();

			//load all sections and pages. 
			List<Section> sections = this.GetAllSections(true);

			string default_section = this.GetDefaultSection();

			foreach (var section in sections)
			{
				foreach (var page in section.Pages)
				{
					if (page.Hide == 0x0)
					{
						SiteMap.tUrl url = new IWS.SiteManager.Core.SiteMap.tUrl();
						url.changefreq = IWS.SiteManager.Core.SiteMap.tChangeFreq.monthly;
						url.changefreqSpecified = true;
						url.loc = string.Format("http://{0}/View/{1}/{2}", host_setting.Value, section.ID, page.Permalink);
						url.lastmod = page.ModifiedUtc.ToString("yyyy-MM-ddThh:mm:ss+00:00");
						url.prioritySpecified = true;
						url.priority = 0.2M;
						urls.Add(url);

						//default page for a section
						if (section.DefaultContentID.HasValue && page.ID == section.DefaultContentID.Value)
						{
							url.changefreq = IWS.SiteManager.Core.SiteMap.tChangeFreq.weekly;
							url.priority = 0.6M;
						}

						//Home page. 
						if (section.ID == default_section && section.DefaultContentID.HasValue && page.ID == section.DefaultContentID.Value)
						{
							url.changefreq = IWS.SiteManager.Core.SiteMap.tChangeFreq.daily;
							url.priority = 1.0M;
							url.prioritySpecified = true;
						}
					}
				}
			}

			sitemap.url = urls.ToArray();

			using (FileStream output = new FileStream(Path.Combine(rootFolder, filename), FileMode.Create, FileAccess.Write))
			{
				Utility.SerializeXml(output, sitemap); //will also flush and close the stream. 
			}
		}
	}
}
